package com.yifeng.repo.toolkit.redis.configure;

import com.yifeng.repo.base.utils.redis.worker.RedisCacheWorker;
import com.yifeng.repo.base.utils.redis.worker.RedisLockWorker;
import com.yifeng.repo.toolkit.redis.handler.RedisActionAspectHandler;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by daibing on 2023/2/21.
 */
@Aspect
@Configuration
@ConditionalOnClass({RedisAopProperties.class})
@EnableConfigurationProperties(RedisAopProperties.class)
@ConditionalOnProperty(prefix = "yfcloud.toolkit.redis.aop", name = "enabled")
public class RedisAopConfiguration {
    private final RedisAopProperties properties;
    private RedisActionAspectHandler redisActionAspectHandler;

    @Value("${spring.application.name}")
    private String applicationName;

    public RedisAopConfiguration(RedisAopProperties properties) {
        this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean
    public RedisActionAspectHandler redisActionAspect(RedisCacheWorker redisCacheWorker, RedisLockWorker redisLockWorker) {
        redisActionAspectHandler = new RedisActionAspectHandler(applicationName, properties, redisCacheWorker, redisLockWorker);
        return redisActionAspectHandler;
    }

    @Pointcut("@annotation(com.yifeng.repo.toolkit.redis.annotation.Cache)")
    public void cacheData() {
    }

    @Around("cacheData()")
    public Object cacheData(ProceedingJoinPoint joinPoint) throws Throwable {
        return redisActionAspectHandler.cacheDataByAround(joinPoint);
    }

    @Pointcut("@annotation(com.yifeng.repo.toolkit.redis.annotation.DelCache)")
    public void delCache() {
    }

    @AfterReturning("delCache()")
    public void delCache(JoinPoint joinPoint) throws Throwable {
        redisActionAspectHandler.delCacheByAfterReturning(joinPoint);
    }

    @Pointcut("@annotation(com.yifeng.repo.toolkit.redis.annotation.Lock)")
    public void lockCache() {
    }

    @Around("lockCache()")
    public Object lockCache(ProceedingJoinPoint joinPoint) throws Throwable {
        return redisActionAspectHandler.lockCacheByAround(joinPoint);
    }
}
